using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Web.Mvc;
using SimpleServiceBus.EndpointManagement.Wcf.Contracts.Data;
using SimpleServiceBus.EndpointManagement.Wcf.Contracts.Operation;
using SimpleServiceBus.EndpointMonitor.Web.Helpers.Flot;
using SimpleServiceBus.EndpointMonitor.Web.Models;

namespace SimpleServiceBus.EndpointMonitor.Web.Controllers
{
    public class EndpointController : Controller
    {
        private readonly IEndpointManagementWebService _monitorService;
        protected readonly IRequestParameterProvider _params;

        private static readonly WebChannelFactory<IEndpointManagementWebService> ProxyFactory =
            new WebChannelFactory<IEndpointManagementWebService>("IEndpointManagementWebService");
        
        public EndpointController()
        {
            _monitorService = ProxyFactory.CreateChannel();
            _params = new DefaultRequestValueProvider();
        }

        public EndpointController(IEndpointManagementWebService monitorService, IRequestParameterProvider parameterProvider)
        {
            _monitorService = monitorService;
            _params = parameterProvider;
        }

        public ActionResult Detail(string endpointId)
        {
            if (String.Compare(endpointId, "All", true) == 0)
                return All();

            var endpoint = _monitorService.GetEndpoint(endpointId);

            if (endpoint != null)
            {
                return View(new EndpointViewData
                                {
                                    Endpoint = endpoint,
                                    Top25Errors = _monitorService.GetEndpointErrorsByEndpointId(endpointId,25)
                                });
            }
            return View("EndpointNotFound");
        }

        public ActionResult ErrorDetail(string endpointId, string errorId)
        {
            if (String.Compare(errorId, "All", true) == 0)
                return ErrorsToday(endpointId);

            EndpointErrorContract error = _monitorService.GetEndpointError(errorId);
            return View("Error", error);
        }

        public ActionResult All()
        {
            IList<ManagedEndpointContract> endpoints = _monitorService.GetAllEndpoints();
            IList<EndpointErrorContract> recentErrors = _monitorService.GetEndpointErrors(25);

            return View("List", new EndpointListViewData {Endpoints = endpoints,RecentErrors = recentErrors});

        }

        public ActionResult ErrorsToday(string endpointId)
        {
            return Errors(endpointId, DateTime.Today);
        }

        public ActionResult ErrorsByDate(string endpointId,string year,string month,string day)
        {
            DateTime date;
            if (!DateTime.TryParse(string.Format("{0}/{1}/{2}",month,day,year),out date))
                date = DateTime.Today;
            return Errors(endpointId, date);
        }

        [ActionName("TimeSeries")]
        public ContentResult TimeSeriesQuery(string endpointId, string metrics, DateTime? startTime, DateTime? endTime)
        {
            NameValueCollection parms = _params != null ? _params.RequestParameters : null;

            var dataSet = _monitorService.TimeSeriesQuery(endpointId, metrics, startTime ?? default(DateTime), endTime ?? default(DateTime));
            return new ContentResult {Content = dataSet.ToFlotJson(parms), ContentType = "application/json"};
        }


        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            try
            {
                ((IClientChannel)_monitorService).Close();
            }
            catch
            {
                ((IClientChannel)_monitorService).Abort();
            }
        }

        private ActionResult Errors(string endpointId, DateTime beginDate)
        {
            ManagedEndpointContract endpoint = null;
            bool all = (String.Compare(endpointId, "All", true) == 0);

            if (!all)
            {
                endpoint = _monitorService.GetEndpoint(endpointId);
                if (endpoint == null)
                    return View("EndpointNotFound");
            }


            beginDate = beginDate.ToUniversalTime();

            DateTime endDate = beginDate.AddHours(24).AddSeconds(-1);

            IList<EndpointErrorContract> errors = !all
                                                      ? _monitorService.GetEndpointErrorsByEndpointId(endpointId, 10000)
                                                      : _monitorService.GetEndpointErrors(10000);

            return View("Errors",
                        new EndpointErrorListViewData {Endpoint = endpoint, ErrorDate = beginDate, Errors = errors});

        }

    }
}
